/**
 * \file value.c
 **/

#include <string.h>
#include "value.h"
#include "hash.h"
#include "tuple.h"

bool r_value_equal(RValue a, RValue b)
{
  if (a.type != b.type) return false;
  if (r_value_is_bool(a)) return true;

  /* TODO: This is problematic, bit-by-bit comparison is flawed because of the
   * possibility of padding bits. */
  if (memcmp(&a, &b, sizeof(RValue)) == 0)
    return true;
  else {
    /* TODO: do a string comparison */

    /* Tuple comparison: each element of a tuple is equal. */
    if (r_value_is_tuple(a)){
      /* They have the same size: (see top of this function) */
      int size = r_tuple_size(a);
      int i;
      for (i = 0; i < size; i++){
        if (not r_value_equal(a.val_tuple[i], b.val_tuple[i]))
          return false;
      }
      /* TODO: Warning! This leads to a possible infinite recursion! */
      return true;
    }

    return false;
  }
}

uint32_t r_value_hash(RValue v)
{
  /* TODO: check if it's a string. */

  /* Hash a tuple (2 tuples with same contents have a same hash): */
  if (r_value_is_tuple(v)){
    uint32_t hash = 0;
    int i;
    for (i = 0; i < r_tuple_size(v); i++){
      hash += r_value_hash(v.val_tuple[i]);
    }
    /* TODO: Warning! This leads to a possible infinite recursion! */
    return hash;
  }

  if (r_value_is_true(v))
    return 0xabcdef12;
  if (r_value_is_false(v))
    return 0x456789ab;

  /* TODO: Write a specialized hash function for RValue (unroll r_hash_data
   * for the case of sizeof(RValue).  */
  return r_hash_data((const char*) &v, sizeof(RValue));
}
